로딩 중이에요... 🐣
06 회원가입 기능 구현 (UserCreationForm + Tailwind 기반) | ✅ 편저: 코담 운영자
6강 - 회원가입 기능 구현 (UserCreationForm + Tailwind 기반)
form 사용✨ 이번 강의 목표
이 강의에서는 Django의 UserCreationForm
을 확장하여 사용자 정의 회원가입 기능을 구현합니다. 기본 폼 구성 외에도 Tailwind CSS를 활용한 사용자 친화적인 입력 UI 구성과 함께, 실제 서비스에서 사용하는 비밀번호 검증, 자동 로그인 등의 흐름까지 다룹니다.
- Django
UserCreationForm
기반 사용자 정의 회원가입 폼 구현 - password1, password2를 이용한 비밀번호 검증 처리
- 위젯을 활용한 Tailwind CSS 스타일링 적용
- 자동 로그인 및 리다이렉트 흐름 구현
📌 1. 회원가입 흐름 요약
회원가입의 전반적인 흐름을 이해하면 이후 구현 작업이 훨씬 수월해집니다. Django는 폼 처리, 검증, 저장, 로그인까지의 전체 과정을 구조화된 방식으로 처리할 수 있도록 도와줍니다.
- 사용자가 회원가입 페이지 접속
- 이메일, 이름, 아이디, 비밀번호, 프로필 정보 입력
- 서버에서 폼 유효성 검증
- DB에 사용자 저장
- 자동 로그인 후 posts:index로 리다이렉트
🧾 2. 사용자 정의 회원가입 폼 구현
Django의 UserCreationForm
을 상속하면 기본적으로 비밀번호 필드가 포함되어 있으며, 이를 기반으로 사용자 모델의 커스텀 필드를 함께 처리할 수 있습니다. 이 예제에서는 Tailwind CSS와 함께 폼의 스타일을 지정하고, clean()
메서드를 통해 비밀번호 일치 검증까지 수행합니다.
users/forms.py
from django import forms as django_forms
from django.contrib.auth.forms import UserCreationForm
from .models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
classStyle = """w-full p-3 border border-gray-300 rounded-lg text-sm \
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"""
fileInputStyle=""" file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold \
file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100 cursor-pointer """
fields = (
"email", "name", "username", "profile_photo", "website",
"bio", "gender", "password1", "password2"
)
widgets = {
'email': django_forms.EmailInput(attrs={'required': 'required', 'class': classStyle}),
'name': django_forms.TextInput(attrs={'required': 'required', 'class': classStyle}),
'username': django_forms.TextInput(attrs={'required': 'required', 'class': classStyle}),
'profile_photo': django_forms.ClearableFileInput(attrs={'class': classStyle + fileInputStyle }),
'website': django_forms.URLInput(attrs={'class': classStyle}),
'bio': django_forms.Textarea(attrs={'class': classStyle}),
'gender': django_forms.Select(attrs={'class': classStyle, 'required': 'required'}),
}
labels = {
'email': '이메일',
'name': '성명',
'username': '사용자이름(아이디)',
'profile_photo': '프로필 사진',
'website': '웹사이트',
'bio': '소개',
'gender': '성별',
'password1': '비밀번호',
'password2': '비밀번호 확인',
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password1'].widget.attrs.update({'class': self.Meta.classStyle, 'required': 'required'})
self.fields['password2'].widget.attrs.update({'class': self.Meta.classStyle, 'required': 'required'})
def clean(self):
cleaned_data = super().clean()
password1 = cleaned_data.get("password1")
password2 = cleaned_data.get("password2")
if password1 != password2:
raise django_forms.ValidationError("비밀번호가 일치하지 않습니다.")
return cleaned_data
UserCreationForm
을 기반으로 Tailwind 스타일, 커스터마이징, password 확인 처리까지 반영된 실제 회원가입 폼입니다.
🌐 3. URL 설정
users/urls.py
from django.urls import path
from . import views
app_name = "users"
urlpatterns = [
path('', views.main, name="main"),
path('signup/', views.signup, name="signup"),
]
🧭 4. 회원가입 뷰 구현
뷰(View)는 사용자의 요청을 처리하고, 폼 데이터를 검증 및 저장한 뒤 결과에 따라 적절한 응답을 반환합니다. 이 과정에서 form.save(commit=False)
는 DB에 저장 전 사용자 객체를 반환하고, set_password()
를 호출하여 비밀번호를 안전하게 해시 처리합니다. 이후 authenticate()
로 인증하고 login()
을 호출하여 자동 로그인까지 처리합니다.
users/views.py
from django.shortcuts import render
from django.urls import reverse
from django.contrib.auth import authenticate, login
from django.http import HttpResponseRedirect
from .forms import SignUpForm
def signup(request):
if request.method == "GET":
form = SignUpForm()
return render(request, 'users/signup.html', {'form': form})
elif request.method == "POST":
form = SignUpForm(request.POST, request.FILES)
if form.is_valid():
user = form.save(commit=False)
user.set_password(form.cleaned_data['password1'])
user.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return HttpResponseRedirect(reverse('posts:index'))
return render(request, 'users/signup.html', {'form': form})
🖼️ 5. 회원가입 템플릿 (Tailwind 적용)
templates/users/signup.html
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>
<div class="w-full flex flex-col items-center justify-center min-h-screen bg-gray-100">
<div class="w-full bg-white p-8 rounded-lg shadow-md max-w-lg md:max-w-2xl text-center">
<h1 class="text-2xl font-bold text-gray-800 mb-6">회원가입</h1>
<form action="{% url 'users:signup' %}" method="post" class="space-y-4" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="flex flex-col text-left">
<div class="grid grid-cols-10 gap-2 items-center">
<label class="col-span-3 text-gray-700 font-medium">
{{ field.label_tag }}
</label>
<div class="col-span-7">
{{ field }}
</div>
</div>
<div class="grid grid-cols-10 gap-2 items-center">
<div class="col-span-3"></div>
<div class="!text-red-500 col-span-7 text-sm mt-1">{{ field.errors }}</div>
</div>
</div>
{% endfor %}
<button type="submit" class="w-full py-3 bg-blue-500 text-white text-lg rounded-lg hover:bg-blue-600 transition-colors cursor-pointer">
회원가입
</button>
</form>
<div class="mt-6 text-sm">
이미 계정이 있으신가요?
<a href="{% url 'users:main' %}" class="text-blue-600 hover:underline">로그인</a>
</div>
</div>
</div>
필드마다 Tailwind 스타일을 적용하여 폼 UI를 직관적이고 반응형으로 구성합니다.
⚠️ 실수 방지 체크리스트
문제 | 해결 방법 |
---|---|
비밀번호가 그대로 저장됨 | set_password() 호출 여부 확인 |
회원가입은 되는데 로그인 실패 | authenticate() 와 login() 호출 여부 확인 |
이미지 파일 업로드 안됨 | form 태그에 enctype="multipart/form-data" 포함 여부 확인 |
CSRF 에러 | {% csrf_token %} 누락 여부 확인 |
password2가 무시됨 | clean() 메서드 구현 여부 확인 |
✅ 정리
지금까지 사용자 정의 회원가입 폼을 직접 만들고, 이를 통해 회원가입 → 로그인까지의 전 과정을 구현했습니다. 실무에서는 이메일 인증, 비밀번호 정책 강화 등도 고려되지만, 본 강의는 그 기초 구조를 중심으로 설명하였습니다.
UserCreationForm
을 기반으로 사용자 정의 회원가입 폼을 만들면password1
,password2
입력 및 검증이 가능해집니다.- Tailwind를 활용해 직관적인 입력 폼 UI를 제공할 수 있습니다.
save(commit=False)
+set_password()
패턴은 보안상 필수입니다.- 회원가입 후 자동 로그인 처리까지 흐름을 마무리함으로써 실제 서비스 형태로 작동합니다.
👉 다음 강의에서는 템플릿 상속과 재사용 구조를 설계합니다.